export default class Grain {
  constructor(basicCesium) {
    this.basicCesium = basicCesium
    this.viewer = basicCesium.viewer;

    this.lng = 34.6169472
    this.lat = 47.6458037

    this.entity = null;
    this.particleSystem = null;

    this.initTime();
    this.initEntity()
  }

  initTime() {
    this.start = Cesium.JulianDate.fromDate(new Date());
    // 设置总时长360秒
    this.stop = Cesium.JulianDate.addSeconds(this.start, 360, new Cesium.JulianDate());
    this.viewer.clock.startTime = this.start.clone();
    this.viewer.clock.stopTime = this.stop.clone();
    this.viewer.clock.currentTime = this.start.clone();
    this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //Loop at the end
    this.viewer.clock.multiplier = 10;
    // this.beginAnimate(false);
    this.viewer.timeline.zoomTo(this.start, this.stop);
  }

  initEntity() {
    if (this.entity != null) return false;
    let cartesian = this.basicCesium.lnglatToWorld(this.lng, this.lat, 500);
    this.entity = this.basicCesium.entityModel(new Cesium.CallbackProperty(() => {
      return cartesian
    }, false), {
      model: {
        uri: 'glb/aircraft.glb',
        minimumPixelSize: 100,
        maximumScale: 10000,
        scale: 1,
        incrementallyLoadTextures: false,
        asynchronous: false
      }
    });
    this.entity.isModel = true;
    this.viewer.trackedEntity = this.entity
    this.beginAnimate()
  }

  beginAnimate(isTrue = true) {
    this.viewer.clock.shouldAnimate = isTrue;
    if (isTrue && this.entity != null && this.entity.position instanceof Cesium.CallbackProperty) {
      let radius = 1.2;
      let positions = this.computedProperty(this.lng, this.lat, radius);
      this.entity.availability = new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
        start: this.start,
        stop: this.stop
      })]);
      this.entity.position = positions;
      this.entity.orientation = new Cesium.VelocityOrientationProperty(positions);
      this.entity.path = {
        resolution: 1,
        material: new Cesium.PolylineGlowMaterialProperty({
          glowPower: 0.2,
          color: Cesium.Color.YELLOW
        }),
        width: 10
      };

      this.viewer.trackedEntity = this.entity;
      this.initParticleSystem();
      this.initEvent();
    }
  }

  initParticleSystem() {
    /**
     * 用于在每个时间步上对粒子施加力的函数
     * @param particle 要施加力的粒子
     * @param dt 自上次更新以来的时间
     */
    function applyGravity(particle, dt) {
      var position = particle.position;
      var gravityVector = Cesium.Cartesian3.normalize(position, new Cesium.Cartesian3());
      Cesium.Cartesian3.multiplyByScalar(gravityVector, 0 * dt, gravityVector); // 设置重力效果大小 -20时效果比较明显
      particle.velocity = Cesium.Cartesian3.add(particle.velocity, gravityVector, particle.velocity);
    }
    // 粒子系统
    this.particleSystem = this.viewer.scene.primitives.add(new Cesium.ParticleSystem({
      image: 'img/fire.png', // 粒子资源，用于广告牌的URI，HTMLImageElement或HTMLCanvasElement。
      imageSize: new Cesium.Cartesian2(60.0, 60.0),
      startColor: Cesium.Color.YELLOW.withAlpha(0.7), //粒子出生时的颜色
      endColor: Cesium.Color.RED.withAlpha(0.3), //当粒子死亡时的颜色
      startScale: 1, //粒子出生时的比例，相对于原始大小
      endScale: 3, //粒子在死亡时的比例
      particleLife: 1, //以秒为单位设置粒子的最小和最大寿命
      // minimumLife: 1, //以秒为单位设置粒子的最短寿命
      // maximumLife: 1, //以秒为单位设置粒子的最大寿命
      speed: 2, //设置以米/秒为单位的最小和最大速度
      // minimumSpeed: 5, //设置以米/秒为单位的最小速度
      // maximumSpeed: 5, //设置以米/秒为单位的最大速度
      emissionRate: 5, //每秒发射的粒子数量
      // bursts: [
      //     // time：在粒子系统生命周期开始之后的几秒钟内将发生突发事件。
      //     // minimum：突发中发射的最小粒子数量
      //     // maximum：突发中发射的最大粒子数量
      //     // new Cesium.ParticleBurst({time: 5.0, minimum: 1, maximum: 10}),   // 当在5秒时，发射的数量为50-100
      //     // new Cesium.ParticleBurst({time: 10.0, minimum: 1, maximum: 10}), // 当在10秒时，发射的数量为200-300
      //     // new Cesium.ParticleBurst({time: 15.0, minimum: 1, maximum: 10})  // 当在15秒时，发射的数量为500-800
      //     new Cesium.ParticleBurst({time: 5.0, minimum: 50, maximum: 100}),   // 当在5秒时，发射的数量为50-100
      //     new Cesium.ParticleBurst({time: 10.0, minimum: 100, maximum: 200}), // 当在10秒时，发射的数量为200-300
      //     new Cesium.ParticleBurst({time: 15.0, minimum: 200, maximum: 300})  // 当在15秒时，发射的数量为500-800
      // ], //数组ParticleBurst，周期性地发射粒子脉冲串
      lifeTime: 60, //多长时间的粒子系统将以秒为单位发射粒子
      loop: true, //是否粒子系统应该在完成时循环它的爆发
      // new Cesium.CircleEmitter(0.5)
      // new Cesium.BoxEmitter(new Cesium.Cartesian3(0.1, 0.1, 0.1))
      // new Cesium.ConeEmitter(Cesium.Math.toRadians(30.0))
      emitter: new Cesium.CircleEmitter(1), //此系统的粒子发射器  共有 BoxEmitter,CircleEmitter,ConeEmitter,SphereEmitter 几类
      emitterModelMatrix: this.computeEmitterModelMatrix(), // 4x4转换矩阵，用于在粒子系统本地坐标系中转换粒子系统发射器
      modelMatrix: this.computeModelMatrix(this.entity, Cesium.JulianDate.now()), // 4x4转换矩阵，可将粒子系统从模型转换为世界坐标
      updateCallback: applyGravity // 强制回调函数--例子：这是添加重力效果
    }));
  }

  // 模型位置
  computeModelMatrix(entity, time) {
    var position = Cesium.Property.getValueOrUndefined(entity.position, time, new Cesium.Cartesian3());
    if (!Cesium.defined(position)) {
      return undefined;
    }
    var orientation = Cesium.Property.getValueOrUndefined(entity.orientation, time, new Cesium.Quaternion());
    var modelMatrix = null;
    if (!Cesium.defined(orientation)) {
      modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position, undefined, new Cesium.Matrix4());
    } else {
      modelMatrix = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation, new Cesium.Matrix3()), position, modelMatrix);
    }
    return modelMatrix;
  }

  // 粒子发射系统的模型位置
  computeEmitterModelMatrix() {
    var hpr = Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0, new Cesium.HeadingPitchRoll());
    var trs = new Cesium.TranslationRotationScale();
    trs.translation = Cesium.Cartesian3.fromElements(-12.5, 0.0, -1.0, new Cesium.Cartesian3()); // 设置粒子系统相对于模型坐标的偏移
    trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, new Cesium.Quaternion());
    return Cesium.Matrix4.fromTranslationRotationScale(trs, new Cesium.Matrix4());
  }

  computedProperty(longitude, latitude, radius) {
    let property = new Cesium.SampledPositionProperty();
    for (var i = 0; i <= 360; i += 40) {
      // 根据360弧度，每4°一个拐点，随机生成90个点
      let radians = Cesium.Math.toRadians(i);
      let time = Cesium.JulianDate.addSeconds(this.start, i, new Cesium.JulianDate()); // 在总时长360秒中，设置中间点
      // 生成随机的坐标
      let position = Cesium.Cartesian3.fromDegrees(longitude + (radius * 1.5 * Math.cos(radians)), latitude + (radius * Math.sin(radians)), Cesium.Math.nextRandomNumber() * 500 + 50000);
      property.addSample(time, position);
    }
    return property;
  }

  reset() {
    if (this.entity == null) return false;
    let cartesian = this.basicCesium.lnglatToWorld(this.lng, this.lat, 500);
    this.entity.position = new Cesium.CallbackProperty(() => {
      return cartesian;
    }, false)
    this.entity.availability = null;
    this.entity.orientation = null;
    this.viewer.scene.primitives.remove(this.particleSystem)
  }

  updateParticle(isTrue = true) {
    if (!this.particleSystem) return false;
    if (isTrue) {
      this.particleSystem.show = true;
    } else {
      this.particleSystem.show = false;
    }
  }

  initEvent() {
    this.viewer.scene.preRender.addEventListener((scene, time) => {
      this.particleSystem.modelMatrix = this.computeModelMatrix(this.entity, time);
      this.particleSystem.emitterModelMatrix = this.computeEmitterModelMatrix();
    })
  }
}